package org.com.mars.controller.system;

import java.io.IOException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.com.fw.util.EncryptUtil;
import org.com.fw.util.StringUtil;
import org.com.mars.pojo.system.SysUser;
import org.com.mars.service.system.SysUserService;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping({ "/login.xht" })
public class LoginController {
	
	@Resource
	private SysUserService sysUserService;
	
	@Resource
	private AuthenticationManager authenticationManager;
	
	@Resource
	private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
	
	// login后跳转路径
	private String succeedUrl = "/home.xht";

	@RequestMapping
	public void login(HttpServletRequest request, HttpServletResponse response,
			@RequestParam("username") String username, 
			@RequestParam("password") String password) throws IOException {
		SecurityContextHolder.clearContext();
		
		// 是否输入用户名判断
		if (StringUtil.isEmpty(username)) {
			request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION", "用户名为空。");
			throw new AccessDeniedException("用户名输入为空!");
		}
		
		// 是否输入密码判断
		if (StringUtil.isEmpty(password)) {
			request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION", "密码为空。");
			throw new AccessDeniedException("密码输入为空!");
		}
		
		SysUser sysUser = sysUserService.getSysUserByUserAccount(username);
		String encrptPassword = EncryptUtil.encryptSha256(password);
		
		if ((sysUser == null) || (!encrptPassword.equals(sysUser.getPassword()))) {
			request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION", "用户名或密码输入错误。");
			throw new AccessDeniedException("用户名或密码输入错误!");
		}
		
		// 身份认证
		// （1）用户名和密码获得之后组合成 UsernamePasswordAuthenticationToken 的实例（前文讨论过的Authentication接口的实例）
		// （2）将该令牌传递给 AuthenticationManager 实例进行验证
		// （3）验证成功后，AuthenticationManager 会返回填充好的 Authentication 实例
		// 通过调用 SecurityContextHolder.getContext().setAuthentication(...) 建立安全上下文的实例，传递到返回的身份认证对象上
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
				password);
		authRequest.setDetails(new WebAuthenticationDetails(request));
		SecurityContext securityContext = SecurityContextHolder.getContext();
		// 执行 MarsUserDetailsService 方法
		Authentication auth = authenticationManager.authenticate(authRequest);
		securityContext.setAuthentication(auth);

		// session策略
		// 再通过sessionStrategy执行session固化、并发处理  
		// 判断session是否过期、把当前用户放入session
		sessionStrategy.onAuthentication(auth, request, response);
		
		response.sendRedirect(request.getContextPath() + this.succeedUrl);

	}

}